//ArquivoBinarioMotoristaDAO.java
//Classe dao do Motorista para arquivo binário
//Observação: um registro de um motorista possui 252 bytes
package dao;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import modelo.Motorista;

/**
 * @author Diego Heusser
 * @author Eder Schramm
 */
public class ArquivoBinarioMotoristaDAO extends ArquivoBinarioDAO implements MotoristaDAO {

    @Override
    public boolean inserir(Motorista umMotorista) {
        try {
            File file = new File(motorista_url, nome_motorista);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            RegistroMotorista registro = new RegistroMotorista();
            if (inicio_motorista == -1) {
                inicio_motorista = qtdArquivos(raf, registro.getTamanho());
                registro.escreve(raf, inicio_motorista, -1, umMotorista);
                atualizaConfiguracao();
            } else {
                int identificador = qtdArquivos(raf, registro.getTamanho());
                raf.seek((identificador * registro.getTamanho()) - 4);
                raf.writeInt(identificador);
                registro.escreve(raf, identificador, -1, umMotorista);
            }
            raf.close();
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    @Override
    public boolean alterar(Motorista umMotorista) {
        try {
            File file = new File(motorista_url, nome_motorista);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            List<Motorista> lista = new ArrayList<>();

            RegistroMotorista registro = new RegistroMotorista();
            raf.seek(inicio_motorista * registro.getTamanho());
            do {
                registro.ler(raf);
                if (registro.getProximo() != -1) {
                    raf.seek(registro.getProximo() * registro.getTamanho());
                }
            } while (registro.getId() != umMotorista.getId());
            raf.seek(registro.getIndentificador() * registro.getTamanho());
            registro.escreve(raf, registro.getIndentificador(), registro.getProximo(), umMotorista);
            raf.close();
            return true;
        } catch (IOException | ParseException ex) {
            ex.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean remover(int id) {
        try {
            if (inicio_motorista == -1) {
                return false;
            }
            File file = new File(motorista_url, nome_motorista);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            List<Motorista> lista = new ArrayList<>();

            RegistroMotorista registro = new RegistroMotorista();
            raf.seek(inicio_motorista * registro.getTamanho());
            do {
                registro.ler(raf);
                if (registro.getProximo() != -1) {
                    raf.seek(registro.getProximo() * registro.getTamanho());
                }
            } while (registro.getId() != id);

            int identificador = registro.getIndentificador();
            int proximo = registro.getProximo();

            if (identificador == inicio_motorista) {
                inicio_motorista = proximo;
                atualizaConfiguracao();
                return true;
            }

            raf.seek(inicio_motorista * registro.getTamanho());
            registro.ler(raf);
            while (raf.getFilePointer() < raf.length()) {
                if (registro.getProximo() == identificador) {
                    raf.seek(raf.getFilePointer() - 4);
                    raf.writeInt(proximo);
                    return true;
                }
                raf.seek(registro.getProximo() * registro.getTamanho());
            }

            return false;
        } catch (IOException | ParseException ex) {
            ex.printStackTrace();
            return false;
        }
    }

    @Override
    public List<Motorista> listar() {
        try {
            if (inicio_motorista == -1) {
                return new ArrayList<>();
            }
            File file = new File(motorista_url, nome_motorista);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            List<Motorista> lista = new ArrayList<>();

            RegistroMotorista registro = new RegistroMotorista();
            raf.seek(inicio_motorista * registro.getTamanho());
            do {
                registro.ler(raf);

                Motorista umMotorista = new Motorista();
                umMotorista.setId(registro.getId());
                umMotorista.setDataNascimento(registro.getDataNascimento());
                umMotorista.setGenero(registro.getGenero());
                umMotorista.setHabilitacao(registro.getHabilitacao());
                umMotorista.setNome(registro.getNome());
                lista.add(umMotorista);

                if (registro.getProximo() != -1) {
                    raf.seek(registro.getProximo() * registro.getTamanho());
                }
            } while (registro.getProximo() != -1);

            return lista;
        } catch (IOException | ParseException ex) {
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public List<Motorista> listarFisico() {
        try {
            File file = new File(motorista_url, nome_motorista);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            List<Motorista> lista = new ArrayList<>();
            RegistroMotorista registro = new RegistroMotorista();
            while (raf.getFilePointer() < raf.length()) {
                Motorista umMotorista = new Motorista();
                registro.ler(raf);
                umMotorista.setId(registro.getId());
                umMotorista.setDataNascimento(registro.getDataNascimento());
                umMotorista.setGenero(registro.getGenero());
                umMotorista.setHabilitacao(registro.getHabilitacao());
                umMotorista.setNome(registro.getNome());
                lista.add(umMotorista);
            }
            return lista;
        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        } catch (ParseException ex) {
            return null;
        }
    }

    @Override
    public boolean idValido(int id) {
        try {
            File file = new File(motorista_url, nome_motorista);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            if (inicio_motorista == -1) {
                raf.close();
                return true;
            }
            RegistroMotorista registro = new RegistroMotorista();
            raf.seek(inicio_motorista * registro.getTamanho());
            do {
                registro.ler(raf);
                if (registro.getId() == id) {
                    raf.close();
                    return false;
                }
                if (registro.getProximo() != -1) {
                    raf.seek(registro.getProximo() * registro.getTamanho());
                }
            } while (registro.getProximo() != -1);
            raf.close();
            return true;
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
            return false;
        } catch (IOException ex) {
            ex.printStackTrace();
            return false;
        } catch (ParseException ex) {
            ex.printStackTrace();
            return false;
        }
    }

    @Override
    public List<Motorista> listar(String nome) {
        try {
            if (inicio_motorista == -1) {
                return new ArrayList<>();
            }
            File file = new File(motorista_url, nome_motorista);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            List<Motorista> lista = new ArrayList<>();

            RegistroMotorista registro = new RegistroMotorista();
            raf.seek(inicio_motorista * registro.getTamanho());
            do {
                registro.ler(raf);

                Motorista umMotorista = new Motorista();
                umMotorista.setId(registro.getId());
                umMotorista.setDataNascimento(registro.getDataNascimento());
                umMotorista.setGenero(registro.getGenero());
                umMotorista.setHabilitacao(registro.getHabilitacao());
                umMotorista.setNome(registro.getNome());
                if (nome.equals(umMotorista.getNome().substring(0, nome.length()))) {
                    lista.add(umMotorista);
                }

                if (registro.getProximo() != -1) {
                    raf.seek(registro.getProximo() * registro.getTamanho());
                }
            } while (registro.getProximo() != -1);

            return lista;
        } catch (IOException | ParseException ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public Motorista listar(int id) {
        try {
            File file = new File(motorista_url, nome_motorista);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            if (inicio_motorista == -1) {
                raf.close();
                return null;
            }
            RegistroMotorista registro = new RegistroMotorista();
            raf.seek(inicio_motorista * registro.getTamanho());
            do {
                registro.ler(raf);
                if (registro.getId() == id) {
                    raf.close();
                    Motorista umMotorista = new Motorista();
                    umMotorista.setDataNascimento(registro.getDataNascimento());
                    umMotorista.setGenero(registro.getGenero());
                    umMotorista.setHabilitacao(registro.getHabilitacao());
                    umMotorista.setId(registro.getId());
                    umMotorista.setNome(registro.getNome());
                    return umMotorista;
                }
                if (registro.getProximo() != -1) {
                    raf.seek(registro.getProximo() * registro.getTamanho());
                }
            } while (registro.getProximo() != -1);
            raf.close();
            return null;
        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        } catch (ParseException ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public Motorista listarFisico(int id) {
        try {
            File file = new File(motorista_url, nome_motorista);
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            if (inicio_motorista == -1) {
                raf.close();
                return null;
            }
            RegistroMotorista registro = new RegistroMotorista();
            while (raf.getFilePointer() < raf.length()) {
                registro.ler(raf);
                if (registro.getId() == id) {
                    raf.close();
                    Motorista umMotorista = new Motorista();
                    umMotorista.setDataNascimento(registro.getDataNascimento());
                    umMotorista.setGenero(registro.getGenero());
                    umMotorista.setHabilitacao(registro.getHabilitacao());
                    umMotorista.setId(registro.getId());
                    umMotorista.setNome(registro.getNome());
                    return umMotorista;
                }
            }
            raf.close();
            return null;
        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        } catch (ParseException ex) {
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public boolean apagarDados() {
        try {
            inicio_motorista = -1;
            atualizaConfiguracao();
            return true;
        } catch (Exception ex ) {
            return false;
        }
    }

    @Override
    public boolean criarTabela() {
        throw new UnsupportedOperationException("Não é possível cria a tabela com Arquivo Binário.");
    }

}
